Performs one of the following operations on a process: checks if it exists; changes its priority; closes it; waits for it to close.
Process, Cmd, PID-or-Name [, Param3]
Cmd | One of the following words: Exist: Sets ErrorLevel to the Process ID (PID) if a matching process exists, or 0 otherwise. In v1.0.36+, if the PID-or-Name parameter is blank, the script's own PID is retrieved. An alternate, single-line method to retrieve the script's PID is PID := DllCall("GetCurrentProcessId") Close: If a matching process is successfully terminated, ErrorLevel is set to its former Process ID (PID). Otherwise (there was no matching process or there was a problem terminating it), it is set to 0. Since the process will be abruptly terminated -- possibly interrupting its work at a critical point or resulting in the loss of unsaved data in its windows (if it has any) -- this method should be used only if a process cannot be closed by using WinClose on one of its windows. List: Although List is not yet supported, the examples section demonstrates how to retrieve a list of processes via DllCall. Priority: Changes the priority (as seen in Windows Task Manager) of the first matching process to Param3 and sets ErrorLevel to its Process ID (PID). If the PID-or-Name parameter is blank, the script's own priority will be changed. If there is no matching process or there was a problem changing its priority, ErrorLevel is set to 0. Param3 should be one of the following letters or words: L (or Low), B (or BelowNormal), N (or Normal), A (or AboveNormal), H (or High), R (or Realtime). Since BelowNormal and AboveNormal are not supported on Windows 95/98/Me/NT4, normal will be automatically substituted for them on those operating systems. Note: Any process not designed to run at Realtime priority might reduce system stability if set to that level. Wait: Waits up to Param3 seconds (can contain a decimal point) for a matching process to exist. If Param3 is omitted, the command will wait indefinitely. If a matching process is discovered, ErrorLevel is set to its Process ID (PID). If the command times out, ErrorLevel is set to 0. WaitClose: Waits up to Param3 seconds (can contain a decimal point) for ALL matching processes to close. If Param3 is omitted, the command will wait indefinitely. If all matching processes are closed, ErrorLevel is set to 0. If the command times out, ErrorLevel is set to the Process ID (PID) of the first matching process that still exists. |
PID-or-Name | This parameter can be either a number (the PID) or a process name as described below. It can also be left blank to change the priority of the script itself. PID: The Process ID, which is a number that uniquely identifies one specific process (this number is valid only during the lifetime of that process). The PID of a newly launched process can be determined via the Run command. Similarly, the PID of a window can be determined with WinGet. The Process command itself can also be used to discover a PID. Name: The name of a process is usually the same as its executable (without path), e.g. notepad.exe or winword.exe. Since a name might match multiple running processes, only the first process will be operated upon. The name is not case sensitive. |
Param3 | See Cmd above for details. |
See Cmd above for details.
For Wait and WaitClose: Processes are checked every 100 milliseconds; the moment the condition is satisfied, the command stops waiting. In other words, rather than waiting for the timeout to expire, it immediately sets ErrorLevel as described above, then continues execution of the script. Also, while the command is in a waiting state, new threads can be launched via hotkey, custom menu item, or timer.
To work under Windows NT4, the Process command requires the file PSAPI.DLL, which is normally already present in the AutoHotkey installation directory (i.e. no extra installation steps should be needed even for NT). However, to use it from within a compiled script on Windows NT4, include a copy of PSAPI.DLL in the same folder as the script or in one of the directories in the system's PATH (though some NT4 systems might already have the DLL).
Run, WinGet, WinClose, WinKill, WinWait, WinWaitClose, IfWinExist
; Example #1:
Run Notepad.exe, , , NewPID
Process, priority, %NewPID%, High
MsgBox The newly launched notepad's PID is %NewPID%.
; Example #2: Process, wait, Notepad.exe, 5.5 NewPID = %ErrorLevel% ; Save the value immediately since ErrorLevel is often changed. if NewPID = 0 { MsgBox The specified process did not appear within 5.5 seconds. return } ; Otherwise: MsgBox A matching process has appeared (Process ID is %NewPID%). Process, priority, %NewPID%, Low Process, priority, , High ; Have the script set itself to high priority. WinClose Untitled - Notepad Process, WaitClose, %NewPID%, 5 if ErrorLevel ; The PID still exists. MsgBox The process did not close within 5 seconds.
; Example #3: A hotkey to change the priority of the active window's process: #z:: ; Win+Z hotkey WinGet, active_pid, PID, A WinGetTitle, active_title, A Gui, 5:Add, Text,, Press ESCAPE to cancel, or double-click a new`npriority level for the following window:`n%active_title% Gui, 5:Add, ListBox, vMyListBox gMyListBox r5, Normal|High|Low|BelowNormal|AboveNormal Gui, 5:Add, Button, default, OK Gui, 5:Show,, Set Priority return 5GuiEscape: 5GuiClose: Gui, Destroy return MyListBox: if A_GuiControlEvent <> DoubleClick return ; else fall through to the next label: 5ButtonOK: GuiControlGet, MyListBox Gui, Destroy Process, Priority, %active_pid%, %MyListBox% if ErrorLevel MsgBox Success: Its priority was changed to "%MyListBox%". else MsgBox Error: Its priority could not be changed to "%MyListBox%". return
; Example #4: Retrieves a list of running processes via DllCall then shows them in a MsgBox. d = `n ; string separator s := 4096 ; size of buffers and arrays (4 KB) Process, Exist ; sets ErrorLevel to the PID of this running script ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400) h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel) ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32) DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t) VarSetCapacity(ti, 16, 0) ; structure of privileges InsertInteger(1, ti, 0, 4) ; one entry in the privileges array... ; Retrieves the locally unique identifier of the debug privilege: DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege", "UIntP", luid) InsertInteger(luid, ti, 4, 8) InsertInteger(2, ti, 12, 4) ; enable this privilege: SE_PRIVILEGE_ENABLED = 2 ; Update the privileges of this process with the new access token: DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false, "UInt", &ti, "UInt", 0, "UInt", 0, "UInt", 0) DllCall("CloseHandle", "UInt", h) ; close this process handle to save memory hModule := DllCall("LoadLibrary", "Str", "Psapi.dll") ; increase performance by preloading the libaray s := VarSetCapacity(a, s) ; an array that receives the list of process identifiers: DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r) Loop, % r // 4 ; parse array for identifiers as DWORDs (32 bits): { id := ExtractInteger(a, A_Index * 4) ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400) h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id) VarSetCapacity(m, s) ; an array that receives the list of module handles: DllCall("Psapi.dll\EnumProcessModules", "UInt", h, "UInt", &m, "UInt", s, "UIntP", r) VarSetCapacity(n, s, 0) ; a buffer that receives the base name of the module: e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", m, "Str", n, "Chr", s) DllCall("CloseHandle", "UInt", h) ; close process handle to save memory If n ; if image is not null add to list: l = %l%%n%%d% } DllCall("FreeLibrary", "UInt", hModule) ; unload the library to free memory ; Remove the first and last items in the list (possibly ASCII signitures) StringMid, l, l, InStr(l, d) + 1, InStr(l, d, false, 0) - 2 - InStr(l, d) StringReplace, l, l, %d%, %d%, UseErrorLevel ; gets the number of processes ;Sort, l, C ; uncomment this line to sort the list alphabetically MsgBox, 0, %ErrorLevel% Processes, %l% ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4) ; See DllCall for details. { Loop %pSize% ; Build the integer by adding up its bytes. result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1) if (!pIsSigned OR pSize > 4 OR result < 0x80000000) return result ; Signed vs. unsigned doesn't matter in these cases. return -(0xFFFFFFFF - result + 1) } InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) { Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data. DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF) }